home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 08 - 1992 / 08.01 Apr⁄May 92 / ~3D Animation / asm version / Tutor3D[asm].c < prev   
Encoding:
C/C++ Source or Header  |  1992-04-23  |  21.3 KB  |  628 lines  |  [TEXT/KAHL]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Program:    Tutor3D™
  4. #
  5. #    Copyright ©1991 Lincoln Lydick
  6. #    All Rights Reserved.
  7. #
  8. #
  9.  
  10. NOTES
  11. -----
  12.     Include the following libraries:
  13.         MacTraps
  14.         SANE
  15.  
  16.     The initialization is in C, we use C declarations, and the event
  17.     loop is in assembly.
  18.  
  19.     For an overall explanation of what's happening at each routine, see
  20.     the THINK C code.
  21. -----------------------------------------------------------*/
  22.  
  23. #include     "SANE.h"                                        /*    for initialization only.    */
  24.  
  25. #define        kCenterH                    256                /*    this is origin.h    */
  26. #define        kCenterV                    171                /*    this is origin.v    */
  27. #define        kMaxObjects                6                    /*    max num objects we draw    */
  28. #define        kAngleResolution        12                /*    minutes per deqree (never 0)    */
  29. #define        kProjDistance            450                /*    distance to projection plane    */
  30. #define        kLineToTrapNum        0xA891        /*    trap num for _LineTo    */
  31. #define        kNotBWAlertNum        256                /*    ALRT id for monitor bit depth > 1 */
  32.  
  33. enum     ObjectType        {cube, pyramid};        /*    we define two types of objects    */
  34.  
  35. typedef struct {short    x, y, z;
  36. } Point3D;            /*    structure for a 3 dimensional pt.    */
  37.  
  38. typedef    struct {
  39.     Point3D            pt3D;
  40.     short            angle, sine, cosine;
  41. } ViewerInfo;    /*    structure for viewer's position.    */
  42.  
  43. typedef    struct {
  44.     enum ObjectType    objType;
  45.     Point3D            pt3D;
  46.     short            angle, halfWidth, height;
  47.     Boolean            rotates, moves;
  48. } ObjectInfo;        /*    structure for an object.    */
  49.  
  50. typedef    short    TrigTable[1];
  51.  
  52. TrigTable            *gTrigTable;
  53. ViewerInfo        gViewer;
  54. ObjectInfo            gObject[kMaxObjects];
  55. BitMap                gBitMap;
  56. GrafPort            gAnimationPort;
  57. Rect                    gVisRect;
  58. Point                    gVertex[8];
  59. Point3D                gDelta;
  60. Ptr                    gLineToAddress;
  61. short                gDiffRows;
  62.  
  63. /************************************************************/
  64. /*    
  65. /*    Assign parameters to an object (a cube or pyramid).
  66. /*    
  67. /************************************************************/
  68. static void NewObject(short index, enum ObjectType    theType, short width, short height,
  69.     Boolean rotates, Boolean moves, short x, short y, short z)
  70. {
  71.     register    ObjectInfo        *obj;
  72.     
  73.     obj = &gObject[index];
  74.     obj->objType = theType;
  75.     obj->halfWidth = width/2;
  76.     obj->height = height;
  77.     obj->rotates = rotates;
  78.     obj->moves = moves;
  79.     obj->angle = 0;
  80.     obj->pt3D.x = x;
  81.     obj->pt3D.y = y;
  82.     obj->pt3D.z = z;
  83. }
  84.  
  85. /************************************************************/
  86. /*    
  87. /*    Initialize of all our globals, build the trig table, set up an offscreen buffer, create a new
  88. /*    window, and initialize all the objects to be drawn.
  89. /*    
  90. /************************************************************/
  91. static void Initialize(void)
  92. {
  93.     WindowPtr    gWindow;
  94.     extended        angle;
  95.     short            i;
  96.  
  97.     InitGraf(&thePort);
  98.     InitFonts();
  99.     InitWindows();
  100.     InitMenus();
  101.     TEInit();
  102.     InitDialogs(0L);
  103.     InitCursor();
  104.     FlushEvents(everyEvent, 0);
  105.     SetCursor(*GetCursor(crossCursor));
  106.  
  107.     if ((*(*GetMainDevice())->gdPMap)->pixelSize > 1)
  108.     {
  109.         InitCursor();
  110.         StopAlert(kNotBWAlertNum, NULL);    /* tell user to switch to B&W.*/
  111.         ExitToShell();
  112.     }
  113.  
  114.     gLineToAddress = (Ptr) NGetTrapAddress(kLineToTrapNum, ToolTrap);
  115.     gLineToAddress = StripAddress(gLineToAddress);
  116.  
  117.     gTrigTable = (TrigTable*)NewPtr(((90*kAngleResolution)+1)*2);
  118.     for (i = 0, angle = 0.00; i <= 90*kAngleResolution; i++, angle += 0.017453292/kAngleResolution)    
  119.         *gTrigTable[i] = sin(angle)*1000;    /*    save the value (x1000) in an array.*/
  120.  
  121.         /*    give the viewer an initial direction and position…*/
  122.     gViewer.angle = gViewer.sine = gViewer.pt3D.x = gViewer.pt3D.y = 0;    
  123.     gViewer.pt3D.z = 100;
  124.     gViewer.cosine = 999;
  125.  
  126.     NewObject(0, cube, 120, 120, false, false, -150, 600, 0);    /*    create some objects…*/
  127.     NewObject(1, cube, 300, 300, true, false, -40, 1100, 60);
  128.     NewObject(2, cube, 40, 10, true, true, 0, 500, 0);
  129.     NewObject(3, pyramid, 160, 160, false, false, 200, 700, 0);
  130.     NewObject(4, pyramid, 80, -80, true, false, 200, 700, 240);
  131.     NewObject(5, pyramid, 60, 60, false, false, -40, 1100, 0);
  132.  
  133.     SetRect(&gVisRect, -100, -100, 512+100, 342+100);    /*    visible bounds for objects.*/
  134.     SetRect(&gBitMap.bounds, 0, 0, 512, 342);
  135.     gBitMap.rowBytes = ((512+15)/16)*2;
  136.     gBitMap.baseAddr = NewPtr(342*(((512+15)/16)*2));    /*    allocate bit map*/
  137.  
  138.     gWindow = NewWindow(0L, &gBitMap.bounds, "\p", true, 2, (Ptr)-1, false, 0);
  139.     gDiffRows = gWindow->portBits.rowBytes - gBitMap.rowBytes;
  140.  
  141.     OpenPort(&gAnimationPort);        /*    we draw to an offscreen buffer.*/
  142.     SetPort(&gAnimationPort);
  143.     SetPortBits(&gBitMap);
  144.     PenPat(white);
  145. }
  146.  
  147. /************************************************************/
  148. /*    
  149. /*    Here's the assembly. VERY IMPORTANT!! Several low memory globals are used
  150. /*    and could cause serious problems on different or future macs. Also, a couple of
  151. /*    numbers are "hard coded" and rely on others - not allowing for much flexibility.
  152. /*    This is, however, not an example of how to program the 680x0 or proper ROM
  153. /*    useage, but does show some ways to speed things up.
  154. /*    
  155. /************************************************************/
  156. void main(void)
  157. {    asm    {    
  158.  
  159. ;------Start------
  160. ;    The Main Event (loop). Cycle until the mouse button is pressed.
  161.  
  162.                     jsr            Initialize                        ;    set up params…
  163.     mainloop:    jsr            @_FillPortBlack            ;    fill the bitmap with black
  164.                     jsr            @_CheckViewer            ;    get scoop on viewer
  165.                     jsr            @_DrawObjects            ;    our drawing pipeline
  166.                     jsr            @_DrawCrossHair            ;    simple crosshair
  167.                     jsr            @_BitBlit                        ;    copy it to the screen
  168.                     tst.b            0x172                            ;    MBState=$172, hardware mouse button state [byte] I-279
  169.                     bmi            @mainloop                        ;    if not, loop.
  170.  
  171.                     moveq        #0x0000000A, d0        ;    mDownMask+keyDownMask, 0
  172.                     _FlushEvents                                    ;    flush em out of the queue
  173.                     _ExitToShell                                    ;    bye…
  174.  
  175. ;------DrawCrossHair------
  176. ;    Draw a crosshair at the center of the window.
  177. ;
  178. @_DrawCrossHair:
  179.                     move.l        #0x00A10100, gAnimationPort.pnLoc        ;    ie., MoveTo(256, 161)
  180.                     move.l        #0x00140000, -(SP)                                ;    ie., 0, 20
  181.                     _Line
  182.                     move.l        #0x00AB00F6, gAnimationPort.pnLoc        ;    246, 171
  183.                     move.l        #0x00000014, -(SP)                                ;    20, 0
  184.                     _Line
  185.                     rts
  186.  
  187. ;------FillPortBlack------
  188. ;    Replacement for FillRect(). Simply fills the bitmap
  189. ;    with 0xFFFFFFFF (black) by moving 44 bytes per loop.
  190. ;    Note: this map (512*342) can't be filled evenly so we
  191. ;    tack on a little at the end.
  192.  
  193. @_FillPortBlack:
  194.                     lea            @elevenBlacks, a0
  195.                     movem.l    (a0), d1-d7/a1-a4
  196.                     move.w        #496, d0                            ;    496 = (((length * width) / 32 bits) / 11 longs at a time)-1
  197.                     movea.l        gBitMap.baseAddr, a0        ;    ptr to the bitmap's data
  198.     fillLoop:    movem.l    d1-d7/a1-a4, (a0)            ;    a fast fill…
  199.                     adda.l        #44, a0                            ;    moved 44 bytes (11 * 4)
  200.                     dbra            d0, @fillLoop                        ;    loop
  201.                     movem.l    d1-d5, (a0)                        ;    last little bit cause bitmap's not an even MOD 44
  202.                     rts
  203.  
  204. ;------BitBlit------
  205. ;    Replacement for CopyBits(). Calculate the src and dst bitmap
  206. ;    address, and the difference in rowbytes. The difference will
  207. ;    be the amount to add to the dst bitmap (the screen) to move
  208. ;    down a vertical row. We move 16 longs per horizontal
  209. ;    scan line (16 * 32bits = 512) and 342 rows (height of map).
  210. ;
  211. ;    This runs over 33% faster than CopyBits() since we know
  212. ;    exactly what to "move" and how to calculate it. HOWEVER, it
  213. ;    is a dangerous practice to copy directly to the screen and
  214. ;    further tests should be performed for any serious application.
  215.  
  216. @_BitBlit:
  217.                     _HideCursor                                            ;    don't want to interfere w/ cursor image
  218.                     movea.l            gBitMap.baseAddr, a0        ;    source bitmap ptr
  219.                     movea.l            0x824, a1                        ;    ScrnBase=$824, Screen base [pointer] I-473
  220.                     move.w            #342-1, d0                        ;    342 rows to transfer
  221.                     move.w            gDiffRows, d1
  222.     nextline:    move.l            (a0)+, (a1)+                        ;    first 32 bits of the 512
  223.                     move.l            (a0)+, (a1)+                        ;    second, and so on…
  224.                     move.l            (a0)+, (a1)+
  225.                     move.l            (a0)+, (a1)+
  226.                     move.l            (a0)+, (a1)+
  227.                     move.l            (a0)+, (a1)+
  228.                     move.l            (a0)+, (a1)+
  229.                     move.l            (a0)+, (a1)+
  230.                     move.l            (a0)+, (a1)+
  231.                     move.l            (a0)+, (a1)+
  232.                     move.l            (a0)+, (a1)+
  233.                     move.l            (a0)+, (a1)+
  234.                     move.l            (a0)+, (a1)+
  235.                     move.l            (a0)+, (a1)+
  236.                     move.l            (a0)+, (a1)+
  237.                     move.l            (a0)+, (a1)+
  238.                     adda.w            d1, a1                            ;    move source down a row
  239.                     dbra                d0, @nextline                ;    loop
  240.                     _ShowCursor                                    ;    bring it back
  241.                     rts
  242.  
  243. ;------MyPtInRect------
  244. ;    Replacement for _PtInRect.
  245. ;    ->a0 = Rect *r
  246. ;    ->d0 = Point pt, 
  247.  
  248. @_MyPtInRect:
  249.                     moveq        #0, d1
  250.                     cmp.w        OFFSET(Rect, left)(a0),  d0        ;    compare (left, h)
  251.                     blt            @ptNRect
  252.                     cmp.w        OFFSET(Rect, right)(a0),  d0        ;    compare (right, h)
  253.                     bgt            @ptNRect
  254.                     swap            d0                                                ;    try the vertical.
  255.                     cmp.w        OFFSET(Rect, top)(a0),  d0        ;    compare (top, v)
  256.                     blt            @ptNRect
  257.                     cmp.w        OFFSET(Rect, bottom)(a0),  d0    ;    compare (bottom, v)
  258.                     bgt            @ptNRect
  259.                     moveq        #1, d1
  260.     ptNRect:    tst.b            d1                                                ;    set CCR for caller.
  261.                     rts
  262.  
  263. ;------GetTrigValues------
  264. ;    Determine the sine and cosine values for an angle using our trig table.
  265. ;    <->a0 = *angle
  266. ;    <->a1 = *sine
  267. ;    <->a2 = *cosine
  268. ;    uses a3, d0, d1
  269.  
  270. @_GetTrigValues:
  271.                     cmpi.w        #360*kAngleResolution, (a0)    ;    angle >= 360 degrees?
  272.                     blt            @trig1                                        ;    nope, branch
  273.                     addi.w        #-360*kAngleResolution, (a0)    ;    subtract 360 degrees.
  274.                     bra            @trig2
  275.         trig1:    tst.w        (a0)                                            ;    angle < 0?
  276.                     bge            @trig2                                        ;    nope, branch
  277.                     addi.w        #360*kAngleResolution, (a0)    ;    add 360 degrees to angle
  278.     
  279.         trig2:    move.w        (a0), d0                                    ;    angle into d0
  280.                     movea.l        gTrigTable, a3                            ;    trig table ptr into a3
  281.  
  282.                     cmpi.w        #90*kAngleResolution, d0        ;    angle <= 90?
  283.                     bgt            @trig180                                    ;    nope, branch
  284.                     add.w        d0, d0                                        ;    address of value is 2*angle
  285.                     move.w        (a3, d0.w), (a1)                        ;    ie., new sine = gTrigTable[angle]
  286.                     move.w        #180*kAngleResolution, d1        ;    90 * 2 = 180
  287.                     sub.w        d0, d1                                        ;    get inverse
  288.                     move.w        (a3, d1.w), (a2)                        ;    ie., new cosine = gTrigTable[90-angle]            
  289.                     rts
  290.  
  291.     trig180:    cmpi.w        #180*kAngleResolution, d0        ;    angle <= 180 degrees?
  292.                     bgt            @trig270                                    ;    nope, branch
  293.                     move.w        #180*kAngleResolution, d1        ;    
  294.                     sub.w        d0, d1
  295.                     add.w        d1, d1
  296.                     move.w        (a3, d1.w), (a1)                        ;    ie., new sine = gTrigTable[180-angle]
  297.                     addi.w        #-90*kAngleResolution, d0
  298.                     add.w        d0, d0
  299.                     move.w        (a3, d0.w), (a2)                        ;    ie., new cosine = -gTrigTable[angle-90]
  300.                     neg.w        (a2)
  301.                     rts
  302.  
  303.     trig270:    cmpi.w        #270*kAngleResolution, d0        ;    angle <= 270?
  304.                     bgt            @trig360
  305.                     addi.w        #-180*kAngleResolution, d0
  306.                     add.w        d0, d0
  307.                     move.w        (a3, d0.w), (a1)                        ;    ie., new sine = -gTrigTable[angle-180]
  308.                     neg.w        (a1)
  309.                     move.w        #270*kAngleResolution, d0
  310.                     sub.w        (a0), d0
  311.                     add.w        d0, d0
  312.                     move.w        (a3, d0.w), (a2)                        ;    ie., new cosine = -gTrigTable[270-angle]
  313.                     neg.w        (a2)
  314.                     rts
  315.  
  316.     trig360:    move.w        #360*kAngleResolution, d1
  317.                     sub.w        d0, d1
  318.                     add.w        d1, d1
  319.                     move.w        (a3, d1.w), (a1)                        ;    ie., new sine = -gTrigTable[360-angle]
  320.                     neg.w        (a1)
  321.                     addi.w        #-270*kAngleResolution, d0
  322.                     add.w        d0, d0
  323.                     move.w        (a3, d0.w), (a2)                        ;    ie., new cosine = gTrigTable[angle-270]
  324.                     rts
  325.  
  326. ;------CheckViewer------
  327. ;    See if the viewer has moved by checking the mouse and keyboard.
  328. ;    If moved the mouse, slice up the mouse into a velocity and angle factor, then
  329. ;    grab the new sine and cosine values. Finally, find the new position
  330. ;    in the x, y plane and if the 'q' or 'w' key is down, change the z position
  331. ;    as well.
  332.  
  333. @_CheckViewer:
  334.                     move.l        0x830, d0                ;    Mouse=$830; processed mouse location [long] I-36
  335.                     lea            @mouse, a3                ;    temp holding
  336.                     move.l        d0, (a3)                    ;    save mouse position
  337.                     lea            gBitMap.bounds, a0
  338.                     bsr            @_MyPtInRect            ;    see if mouse is in window
  339.                     beq            @endView;                ;    nope, branch
  340.     
  341.                     addi.w        #-kCenterH, OFFSET(Point, h)(a3)    ;    get difference
  342.                     addi.w        #-kCenterV, OFFSET(Point, v)(a3)
  343.     
  344.                     move.w        OFFSET(Point, h)(a3), d0    ;    get horizontal
  345.                     ext.l            d0                                ;    clear upper 16 bits for divide
  346.                     divs            #10, d0                    ;    slice it up
  347.                     add.w        d0, gViewer.angle        ;    add to old angle
  348.     
  349.                     move.w        OFFSET(Point, v)(a3), d0    ;    get vertical
  350.                     ext.l            d0                                ;    clear upper 16 bits for divide
  351.                     divs            #5, d0                        ;    slice it up
  352.                     neg.w        d0                                ;    need to negate
  353.                     move.w        d0, d7                        ;    save velocity in d7
  354.     
  355.                      lea            gViewer.angle, a0        ;    set up to call routine
  356.                     lea            gViewer.sine, a1
  357.                     lea            gViewer.cosine, a2
  358.                     bsr            @_GetTrigValues        ;    get the new sine/cosine
  359.     
  360.                      move.w        gViewer.sine, d0        ;    the sine into d0
  361.                     muls            d7, d0                        ;    mult by velocity
  362.                     divs            #1000, d0                ;    always divide by 1000
  363.                     add.w        d0, gViewer.pt3D.x    ;    add to old x position
  364.     
  365.                     move.w        gViewer.cosine, d0    ;    the cosine into d0
  366.                     muls            d7, d0                        ;    mult by velocity
  367.                     divs            #1000, d0                ;    always divide by 1000
  368.                     add.w        d0, gViewer.pt3D.y    ;    add to old y position
  369.     
  370.                     move.l        0x174, d0                ;    KeyMap=$174; keyboard bitmap (by code #) [2 longs] I-251
  371.                     btst            #20, d0                    ;    'q'  key
  372.                      beq            @testDn                    ;    is it down?
  373.                     addq.w        #3, gViewer.pt3D.z    ;    add some altitude to the z
  374.         testDn:    btst            #21, d0                    ;    'w'  key
  375.                      beq            @endView                    ;    is it down?
  376.                     addi.w        #-3, gViewer.pt3D.z    ;    subtract some altitude to the z
  377.     endView:    rts
  378.  
  379. ;------Point2Screen------
  380. ;    Rotate a point around the z axis and find it's location in 2D space.
  381. ;    <->a0 = Point *pt
  382. ;    uses d0, d1, d2
  383.  
  384. @_Point2Screen:
  385.                     move.w        gViewer.cosine, d0            ;    [EQ.6]
  386.                     muls            OFFSET(Point, h)(a0), d0    ;    pt.h * cosine
  387.                     divs            #1000, d0                        ;    divide by 1000
  388.                     move.w        gViewer.sine, d1
  389.                     muls            OFFSET(Point, v)(a0), d1    ;    pt.v * sine
  390.                     divs            #1000, d1                        ;    divide by 1000
  391.                     sub.w        d1, d0                                ;    subtract the two, yielding the new horizontal
  392.             
  393.                     move.w        gViewer.sine, d1                ;    [EQ.7]
  394.                     muls            OFFSET(Point, h)(a0), d1    ;    pt.h * sine
  395.                     divs            #1000, d1                        ;    divide by 1000
  396.                     move.w        gViewer.cosine, d2
  397.                     muls            OFFSET(Point, v)(a0), d2    ;    pt.v * cosine
  398.                     divs            #1000, d2                        ;    divide by 1000
  399.                     add.w        d2, d1                                ;    add the two, yielding the new vertical
  400.                     bgt            @project                            ;    if (vertical <= 0) then vertical = 1
  401.                     moveq        #1, d1
  402.             
  403.     project:    muls            #kProjDistance, d0            ;    [EQ.8]. new horizontal * kProjDistance
  404.                     divs            d1, d0                                ;    divide by the vertical
  405.                     addi.w        #kCenterH, d0                    ;    add origin.h (center of window)
  406.                     move.w        d0, OFFSET(Point, h)(a0)    ;    save the new horizontal position
  407.             
  408.                     move.w        #kProjDistance, d0            ;    [EQ.9]
  409.                     muls            gDelta.z, d0                                ;    height * kProjDistance
  410.                     divs            d1, d0                                ;    divide by the vertical
  411.                     addi.w        #kCenterV, d0                    ;    add origin.v (center of window)
  412.                     move.w        d0, OFFSET(Point, v)(a0)    ;    save the new vertical position
  413.                     rts
  414.  
  415. ;------RotateObject------
  416. ;    Rotate an object around the z axis and translate it to the
  417. ;    correct position based on delta.
  418. ;    ->a4 = ObjectInfo     *object
  419. ;    uses a0, a1, a2, a6, d0, d1, d2
  420.  
  421. @_RotateObject:
  422.                     link            a6, #-8                            ;    tempPt = -2(a6), sine = -6(a6), cosine = -8(a6)
  423.                     moveq        #-6*kAngleResolution, d0    ;    pyraminds rotate by -6
  424.                     cmpi.b        #1, OFFSET(ObjectInfo, objType)(a4)    ;    is it a pyramid?
  425.                     beq            @addAngle                        ;    nope, branch
  426.                     moveq        #2*kAngleResolution, d0    ;    cubes rotate by 2
  427.     addAngle:    add.w        d0, OFFSET(ObjectInfo, angle)(a4)    ;    add to old angle
  428.  
  429.                     lea            OFFSET(ObjectInfo, angle)(a4), a0    ;    the angle
  430.                     lea            -6(a6), a1                        ;    the sine
  431.                     lea            -8(a6), a2                        ;    the cosine
  432.                     bsr            @_GetTrigValues                ;    get the sine and cosine of angle
  433.  
  434.                     tst.b            OFFSET(ObjectInfo, moves)(a4)    ;    does object move?
  435.                     beq            @rotate                            ;    nope, branch
  436.  
  437.                     move.w        -6(a6), d0                        ;    sine into d0
  438.                     muls            #20, d0                            ;    velocity = 20
  439.                     divs            #1000, d0                        ;    divide by 1000
  440.                     add.w        d0, OFFSET(ObjectInfo, pt3D.x)(a4);    update new position x
  441.                     move.w        -8(a6), d0                        ;    cosine into d0
  442.                     muls            #-20, d0                            ;    velocity
  443.                     divs            #1000, d0                        ;    divide by 1000
  444.                     add.w        d0, OFFSET(ObjectInfo, pt3D.y)(a4)    ;    update new y
  445.  
  446.         rotate:    moveq        #3, d2                                ;    loop counter (vertices 0 to 3)
  447.                     lea            gVertex, a0                        ;    our array of points
  448.  
  449.         rtLoop:    move.l        (a0), -4(a6)                        ;    tempPt = gVertex[i];
  450.                     move.w        -6(a6), d0                        ;    (sine) compute new vertical
  451.                     muls            -2(a6), d0                        ;    tempPt.h*sine
  452.                     divs            #1000, d0                        ;    divide by 1000
  453.                     move.w        -8(a6), d1                        ;    cosine
  454.                     muls            -4(a6), d1                        ;    tempPt.v*cosine
  455.                     divs            #1000, d1                        ;    divide by 1000
  456.                     add.w        d1, d0                                ;    add em up
  457.                     add.w        gDelta.y, d0                        ;    now translate from origin
  458.                     move.w        d0, (a0)+                            ;    new v position in space
  459.  
  460.                     move.w        -8(a6), d0                        ;    (cosine) compute new horizontal
  461.                     muls            -2(a6), d0                        ;    tempPt.h
  462.                     divs            #1000, d0                        ;    divide by 1000
  463.                     move.w        -6(a6), d1                        ;    sine
  464.                     muls            -4(a6), d1                        ;    tempPt.v*sine
  465.                     divs            #1000, d1                        ;    divide by 1000
  466.                     sub.w        d1, d0                                ;    subtract the two
  467.                     add.w        gDelta.x, d0                        ;    now translate from origin
  468.                     move.w        d0, (a0)+                            ;    new h position in space
  469.  
  470.                     dbra            d2, @rtLoop                        ;    loop
  471.                     unlk            a6                                        ;    kill stackframe
  472.                     rts
  473.  
  474. ;------DrawObjects------
  475. ;    For all of our cubes and pyramids, index thru each
  476. ;    and calculate sizes, translate, rotate, check for visibility,
  477. ;    and finally draw them.
  478. ;    uses a0, a3, a4, d0, d1, d3, & d7 <- (loop counter)
  479.  
  480. @_DrawObjects
  481.                     clr.w        d7                                        ;    d7 is our loop counter
  482.     objloop:    move.w        d7, d0                                ;    start to compute address of object
  483.                     asl.w        #4, d0                                ;    multiply by 16 (size of record)
  484.                     lea            gObject, a4                        ;    our array
  485.                     adda.w        d0, a4                                ;    address of object
  486.  
  487.                     move.w        OFFSET(ObjectInfo, pt3D.x)(a4), d0    ;    [EQ.3]
  488.                     sub.w        gViewer.pt3D.x, d0            ;    pt.x - viewer.x
  489.                     move.w        d0, gDelta.x                        ;    save in delta.x
  490.  
  491.                     move.w        OFFSET(ObjectInfo, pt3D.y)(a4), d0    ;    [EQ.4]
  492.                     sub.w        gViewer.pt3D.y, d0            ;    pt.y - viewer.y
  493.                     move.w        d0, gDelta.y                        ;    save in delta.y
  494.  
  495.                     move.w        gViewer.pt3D.z, d0            ;    [EQ.5]
  496.                     sub.w        OFFSET(ObjectInfo, pt3D.z)(a4), d0
  497.                     move.w        d0, gDelta.z                        ;    save in delta.z
  498.  
  499.                     tst.b            OFFSET(ObjectInfo, rotates)(a4)    ;    do we rotate this one?
  500.                     beq            @staticObj                        ;    nope, branch
  501.  
  502.                     move.w        OFFSET(ObjectInfo, halfWidth)(a4), d0
  503.                     move.w        d0, gVertex[1].h
  504.                     move.w        d0, gVertex[2].h
  505.                     move.w        d0, gVertex[2].v
  506.                     move.w        d0, gVertex[3].v
  507.                     neg.w        d0
  508.                     move.w        d0, gVertex[0].h
  509.                     move.w        d0, gVertex[0].v
  510.                     move.w        d0, gVertex[1].v
  511.                     move.w        d0, gVertex[3].h
  512.  
  513.                     bsr            @_RotateObject                ;    go rotate object at origin
  514.                     bra            @chkType
  515.  
  516.     staticObj:    move.w        OFFSET(ObjectInfo, halfWidth)(a4), d0
  517.                     neg.w        d0
  518.                     move.w        d0, d1
  519.                     add.w        gDelta.x, d0
  520.                     add.w        gDelta.y, d1
  521.                     move.w        d0, gVertex[0].h
  522.                     move.w        d0, gVertex[3].h
  523.                     move.w        d1, gVertex[0].v
  524.                     move.w        d1, gVertex[1].v
  525.                     move.w        OFFSET(ObjectInfo, halfWidth)(a4), d0
  526.                     move.w        d0, d1
  527.                     add.w        gDelta.x, d0
  528.                     add.w        gDelta.y, d1
  529.                     move.w        d0, gVertex[1].h
  530.                     move.w        d0, gVertex[2].h
  531.                     move.w        d1, gVertex[2].v
  532.                     move.w        d1, gVertex[3].v
  533.  
  534.     chkType:    tst.b            OFFSET(ObjectInfo, objType)(a4)    ;    what kind, cube or pyramid?
  535.                     beq            @cube                                ;    not a pyramid, branch
  536.                     move.w        gDelta.x, gVertex[4].h        ;    assine the apex of the pyramid
  537.                     move.w        gDelta.y, gVertex[4].v        ;    ditto
  538.                     bra            @plotZero                            ;    branch
  539.  
  540.         cube:    move.l        gVertex[0], gVertex[4]        ;    assign top plane of cube
  541.                     move.l        gVertex[1], gVertex[5]
  542.                     move.l        gVertex[2], gVertex[6]
  543.                     move.l        gVertex[3], gVertex[7]
  544.  
  545.     plotZero:    lea            gVertex[0], a0                    ;    get vertex 0 first
  546.                     bsr            @_Point2Screen                ;    rotate and plot on window.
  547.  
  548.                     move.l        gVertex[0], d0                    ;    get point
  549.                     lea            gVisRect, a0                        ;    our visable rect
  550.                     bsr            @_MyPtInRect                    ;    check pt in rect…
  551.                     beq            @next                                ;    not visable, branch
  552.  
  553.                     lea            gVertex[1], a0                    ;    rotate and plot on window.
  554.                     bsr            @_Point2Screen
  555.                     lea            gVertex[2], a0                    ;    rotate and plot on window.
  556.                     bsr            @_Point2Screen
  557.                     lea            gVertex[3], a0                    ;    rotate and plot on window.
  558.                     bsr            @_Point2Screen
  559.  
  560.                     move.w        gDelta.z, d0
  561.                     sub.w        OFFSET(ObjectInfo, height)(a4), d0
  562.                     move.w        d0, gDelta.z
  563.                     lea            gVertex[4], a0                    ;    rotate and plot on window.
  564.                     bsr            @_Point2Screen
  565.  
  566.                     movea.l        gLineToAddress, a3
  567.                     move.l        gVertex[0], gAnimationPort.pnLoc    ;    connect the dots…
  568.                     move.l        gVertex[1], -(sp)
  569.                     jsr            (a3)
  570.                     move.l        gVertex[2], -(sp)
  571.                     jsr            (a3)
  572.                     move.l        gVertex[3], -(sp)
  573.                     jsr            (a3)
  574.                     move.l        gVertex[0], -(sp)
  575.                     jsr            (a3)
  576.                     move.l        gVertex[4], -(sp)
  577.                     jsr            (a3)
  578.  
  579.                     tst.b            OFFSET(ObjectInfo, objType)(a4)
  580.                     beq            @drawcube                        ;    not a pyramid, branch
  581.  
  582.                     move.l        gVertex[1], -(sp)
  583.                     jsr            (a3)
  584.                     move.l        gVertex[2], gAnimationPort.pnLoc
  585.                     move.l        gVertex[4], -(sp)
  586.                     jsr            (a3)
  587.                     move.l        gVertex[3], -(sp)
  588.                     jsr            (a3)
  589.  
  590.                     bra            @next
  591.  
  592.     drawcube:    lea            gVertex[5], a0                    ;    rotate and plot on window.
  593.                     bsr            @_Point2Screen
  594.                     lea            gVertex[6], a0                    ;    rotate and plot on window.
  595.                     bsr            @_Point2Screen
  596.                     lea            gVertex[7], a0                    ;    rotate and plot on window.
  597.                     bsr            @_Point2Screen
  598.  
  599.                     movea.l        gLineToAddress, a3
  600.                     move.l        gVertex[5], -(sp)
  601.                     jsr            (a3)
  602.                     move.l        gVertex[6], -(sp)
  603.                     jsr            (a3)
  604.                     move.l        gVertex[7], -(sp)
  605.                     jsr            (a3)
  606.                     move.l        gVertex[4], -(sp)
  607.                     jsr            (a3)
  608.                     move.l        gVertex[1], gAnimationPort.pnLoc
  609.                     move.l        gVertex[5], -(sp)
  610.                     jsr            (a3)
  611.                     move.l        gVertex[2], gAnimationPort.pnLoc
  612.                     move.l        gVertex[6], -(sp)
  613.                     jsr            (a3)
  614.                     move.l        gVertex[3], gAnimationPort.pnLoc
  615.                     move.l        gVertex[7], -(sp)
  616.                     jsr            (a3)
  617.  
  618.         next:    addi.w        #1, d7                                ;    increment counter
  619.                     cmpi.w        #kMaxObjects, d7                ;    last object?
  620.                     blt            @objloop                            ;    loop
  621.                     rts
  622.  
  623. /********************************************************************/
  624.  
  625.     @mouse                dc.l        0
  626.     @elevenBlacks        dc.l        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
  627.         }
  628. }